home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OCFSRC.PAK / OCPART.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  20KB  |  883 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectComponents
  3. // Copyright (c) 1994, 1997 by Borland International, All Rights Reserved
  4. //
  5. // $Revision:   2.16  $
  6. //
  7. // Implementation of TOcPart Class
  8. //----------------------------------------------------------------------------
  9. #include <ocf/pch.h>
  10. #if !defined(OCF_OLEUTIL_H)
  11. # include <ocf/oleutil.h>
  12. #endif
  13. #if !defined(OCF_OCSTORAG_H)
  14. # include <ocf/ocstorag.h>
  15. #endif
  16. #if !defined(OCF_OCPART_H)
  17. # include <ocf/ocpart.h>
  18. #endif
  19. #if !defined(OCF_OCDOC_H)
  20. # include <ocf/ocdoc.h>
  21. #endif
  22. #if !defined(OCF_OCAPP_H)
  23. # include <ocf/ocapp.h>
  24. #endif
  25. #if !defined(OCF_OCVIEW_H)
  26. # include <ocf/ocview.h>
  27. #endif
  28.  
  29. const char  PartFormat[]     = "OcPart.%d";
  30. const char  PartStreamName[] = "\03OcPart";
  31.  
  32. //
  33. // Construct a new part with a given temp id
  34. // Must call Init method to complete initialization
  35. //
  36. TOcPart::TOcPart(TOcDocument& document, int id)
  37. :
  38.   OcDocument(document), BPart(0), BPartI(0), BLPartI(0), Flags(Visible),
  39.   Storage(0)
  40. {
  41.   AddRef();  // TUnknown defaults to 0, we need 1
  42.   if (!id)
  43.     id = OcDocument.AllocPartID();
  44.   char name[32];
  45.   wsprintf(name, PartFormat, id);
  46.   Name = name;
  47.  
  48.   // There must be a Root IStorage associated with each document
  49.   //
  50.   if (!OcDocument.GetStorage())
  51.     TXObjComp::Throw(TXObjComp::xMissingRootIStorage);
  52.  
  53.   // Create a sub-storage from the parent storage in init
  54.   //
  55.   Storage = new TOcStorage(*OcDocument.GetStorage(), name, true, STGM_READWRITE);
  56. }
  57.  
  58. //
  59. // Old style constructor - does init in constructor -
  60. //  OCF messages will get passed before constructor is complete
  61. //
  62. TOcPart::TOcPart(TOcDocument& document, TOcInitInfo far& initInfo,
  63.                  TRect objPos, int id)
  64. :
  65.   OcDocument(document), BPart(0), BPartI(0), BLPartI(0), Flags(Visible),
  66.   Storage(0)
  67. {
  68.   // Part position and size are in logical units
  69.   //
  70.   AddRef();  // TUnknown defaults to 0, we need 1
  71.   if (!id)
  72.     id = OcDocument.AllocPartID();
  73.   char name[32];
  74.   wsprintf(name, PartFormat, id);
  75.   Name = name;
  76.  
  77.   // There must be a Root IStorage associated with each document
  78.   //
  79.   if (!OcDocument.GetStorage())
  80.     TXObjComp::Throw(TXObjComp::xMissingRootIStorage);
  81.  
  82.   // Create a sub-storage from the parent storage in init
  83.   //
  84.   Storage = new TOcStorage(*OcDocument.GetStorage(), name, true, STGM_READWRITE);
  85.   Init (&initInfo, objPos);
  86. }
  87.  
  88. //
  89. // Construct a part from a named stream in an oc doc's storage
  90. //
  91. TOcPart::TOcPart(TOcDocument& document, const char far* name)
  92. :
  93.   OcDocument(document), BPart(0), BPartI(0), BLPartI(0), Flags(Visible),
  94.   Storage(0),
  95.   Name(name)
  96. {
  97.   AddRef();  // TUnknown defaults to 0, we need 1
  98.  
  99.   // There must be an IStorage associated with each document
  100.   //
  101.   if (!OcDocument.GetStorage())
  102.     TXObjComp::Throw(TXObjComp::xMissingRootIStorage);
  103.  
  104.   // Open a sub-storage from the parent storage in init
  105.   //
  106.   Storage = new TOcStorage(*OcDocument.GetStorage(), name, false, STGM_READWRITE);
  107.  
  108.   // Load our data, and then add ourselves to our document's part collection if
  109.   // everthing succeeds. We'll initialize our helper objects when the parts
  110.   // become visible.
  111.   //
  112.   Load();
  113.   OcDocument.GetParts().Add(this);
  114. }
  115.  
  116. //
  117. //
  118. //
  119. TOcPart::~TOcPart()
  120. {
  121.   // Detach this part from its document
  122.   //
  123.   Detach();
  124.  
  125.   // double check if active part is "this" and, in case, delete it
  126.   if (OcDocument.GetActiveView()->GetActivePart() == this)
  127.     OcDocument.GetActiveView()->SetActivePart(NULL);
  128.  
  129.   // Delete any associated storage
  130.   //
  131.   delete Storage;
  132. }
  133.  
  134. //
  135. // Perform common ctor initialization
  136. //
  137. bool
  138. TOcPart::Init(TOcInitInfo far* initInfo, TRect objPos)
  139. {
  140.   if (BPart)
  141.     return false;   // already initialized
  142.  
  143.   // Part position and size are in logical units
  144.   //
  145.   TOcSiteRect siteRect(this, objPos);
  146.   TOcView* view = OcDocument.GetActiveView();
  147.   if (view) {
  148.     view->ContainerHost->EvOcViewSetSiteRect(siteRect);
  149.     Pos = siteRect.Rect.TopLeft();
  150.     Size = siteRect.Rect.Size();
  151.   }
  152.  
  153.   if (InitObj(initInfo)) {
  154.     OcDocument.GetParts().Add(this);
  155.     return true;
  156.   }
  157.   return false;
  158. }
  159.  
  160. //
  161. //
  162. //
  163. bool
  164. TOcPart::InitObj(TOcInitInfo far* initInfo)
  165. {
  166.   // Initialize our helpers & then add ourselves to our document's part
  167.   // collection if everything succeeds
  168.   //
  169.   if (initInfo) {
  170.  
  171.     // There must be an IStorage associated with each part, make sure the ctor
  172.     // got it OK
  173.     //
  174.     initInfo->Storage = Storage->GetIStorage();
  175.  
  176.     // Create part helper
  177.     //
  178.     TXObjComp::Check(
  179.       OcDocument.GetOcApp().BOleComponentCreate(&BPart, GetOuter(), cidBOlePart),
  180.       TXObjComp::xInternalPartError);
  181.  
  182.     // Get the interfaces we need & then release the object itself
  183.     //
  184.     if (HRSucceeded(BPart->QueryInterface(IID_IBPart, &(LPVOID)BPartI)))
  185.       BPartI->Release();
  186.     if (HRSucceeded(BPart->QueryInterface(IID_IBLinkable, &(LPVOID)BLPartI)))
  187.       BLPartI->Release();
  188.  
  189.     HRESULT hr;
  190.     if (!BPartI || !HRSucceeded(hr = BPartI->Init(this, initInfo))) {
  191.       BPart->Release();
  192.       BPart = 0;
  193.       TXObjComp::Throw(TXObjComp::xPartInitError, hr);
  194.     }
  195.  
  196.     Rename();
  197.     if (initInfo->How == ihLink)  // Remember that we are a link
  198.       Flags |= Link;
  199.  
  200.     // New parts become active when they are init'd above. Make sure that our
  201.     // view knows that we are active too.
  202.     //
  203.     if (initInfo->Where == iwNew) {
  204.       Flags |= Active;
  205.       TOcView* activeView = OcDocument.GetActiveView();
  206.       CHECK(activeView);
  207.       activeView->ActivatePart(this);
  208.     }
  209.   }
  210.   return true;
  211. }
  212.  
  213. //
  214. // Delete this object. Actually, causes object to shutdown as much as possible
  215. // & then releases a reference.
  216. //
  217. void
  218. TOcPart::Delete()
  219. {
  220.   Activate(false);
  221.   Close();
  222.   Release();
  223. }
  224.  
  225. //
  226. // Callback from TUnknown's implementation of QueryInterface
  227. //
  228. HRESULT
  229. TOcPart::QueryObject(const IID far& iid, void far* far* iface)
  230. {
  231.   PRECONDITION(iface);
  232.   HRESULT hr;
  233.  
  234.   // interfaces
  235.   //
  236.      HRSucceeded(hr = IBSite_QueryInterface(this, iid, iface))
  237.  
  238.   // helpers
  239.   //
  240.   || (BPart && HRSucceeded(hr = BPart->QueryInterface(iid, iface)))
  241.   ;
  242.   return hr;
  243. }
  244.  
  245. //
  246. // Query server for its interfaces
  247. //
  248. HRESULT
  249. TOcPart::QueryServer(const IID far& iid, void far* far* iface)
  250. {
  251.   PRECONDITION(iface);
  252.   return BPartI->DoQueryInterface(iid, iface);
  253. }
  254.  
  255. //
  256. // Disconnect servers by closing & releasing our BOle helper
  257. //
  258. bool
  259. TOcPart::Close()
  260. {
  261.   if (!BPartI)
  262.     return true;
  263.  
  264.   if (BLPartI)
  265.     BLPartI->OnRename(0, 0);
  266.  
  267.   if (HRSucceeded(BPartI->Close())) {
  268.     // release our BOle helper object
  269.     //
  270.     BPart->Release();
  271.     BPart   = 0;
  272.     BPartI  = 0;
  273.     BLPartI = 0;
  274.  
  275.     // So that it won't get created again in Draw
  276.     //
  277.     Flags |= Closing;
  278.     return true;
  279.   }
  280.   return false;
  281. }
  282.  
  283. //
  284. // Rename the embed site for linking
  285. //
  286. void
  287. TOcPart::Rename()
  288. {
  289.   TOcView* activeView = OcDocument.GetActiveView();
  290.   CHECK(activeView);
  291.  
  292.   IBRootLinkable* bLDocumentI;
  293.   activeView->QueryInterface(IID_IBRootLinkable, &(LPVOID)bLDocumentI);
  294.   activeView->Release();
  295.  
  296.   if (BLPartI && bLDocumentI)
  297.     BLPartI->OnRename(bLDocumentI, GetName());
  298. }
  299.  
  300. //----------------------------------------------------------------------------
  301. // ISite Implementation--delegates site/view related queries/notifies to the
  302. // active view of this part
  303. //
  304.  
  305. //
  306. // Show/hide a site.
  307. //
  308. HRESULT _IFUNC
  309. TOcPart::SiteShow(BOOL show)
  310. {
  311.   Invalidate(invView);
  312.  
  313.   // When this part is activated, the site is hidden. This is a good time to
  314.   // make sure our state is in sync.
  315.   //
  316.   if (!show) {
  317.     // Make sure the view knows about the active part
  318.     //
  319.     Flags |= Active;
  320.     TOcView* view = OcDocument.GetActiveView();
  321.     if (view) {
  322.       view->ActivatePart(this);
  323.       view->ContainerHost->EvOcViewPartActivate(*this);
  324.     }
  325.   }
  326.   return HR_NOERROR;
  327. }
  328.  
  329. //
  330. // Discard undo stack for our associated [the active] view
  331. //
  332. HRESULT _IFUNC
  333. TOcPart::DiscardUndo()
  334. {
  335.   return HR_NOERROR;
  336. }
  337.  
  338. //
  339. // Retrieve the site rect [relative to the active view?], and optionally the
  340. // view's rect too?
  341. //
  342. HRESULT _IFUNC
  343. TOcPart::GetSiteRect(TRect far* posRect, TRect far* clipRect)
  344. {
  345.   PRECONDITION(posRect);
  346.   if (!posRect)
  347.     return HR_INVALIDARG;
  348.  
  349.   TOcView* view = OcDocument.GetActiveView();
  350.   if (!view)
  351.     return HR_FAIL;
  352.   if (posRect) {
  353.     TOcSiteRect siteRect(this, TRect(Pos, Size));
  354.     view->ContainerHost->EvOcViewGetSiteRect(siteRect);
  355.     *posRect = siteRect.Rect;
  356.  
  357.     // If we don't know our site size yet, then fail this call. Let the server
  358.     // pick a size.
  359.     //
  360.     if (posRect->right-posRect->left <= 0 || posRect->bottom-posRect->top <= 0) {
  361.       posRect->right = posRect->left;
  362.       posRect->bottom = posRect->top;
  363.       return HR_FAIL;
  364.     }
  365.   }
  366.  
  367.   if (clipRect)
  368.     view->GetWindowRect(clipRect);
  369.   return HR_NOERROR;
  370. }
  371.  
  372. //
  373. // Set the site's rect from an in-place active part. Since user is in control
  374. // we generally respect both Pos & Size changes.
  375. //
  376. HRESULT _IFUNC
  377. TOcPart::SetSiteRect(const TRect far* newRect)
  378. {
  379.   PRECONDITION(newRect);
  380.   if (!newRect)
  381.     return HR_INVALIDARG;
  382.  
  383.   TOcView* view = OcDocument.GetActiveView();
  384.   if (!view)
  385.     return HR_FAIL;
  386.  
  387.   // Give other views a chance to update
  388.   //
  389.   Invalidate(invView);   // erase old image
  390.  
  391.   TOcSiteRect siteRect(this, *newRect);
  392.   view->ContainerHost->EvOcViewSetSiteRect(siteRect);
  393.   Size = siteRect.Rect.Size();
  394.   Pos  = siteRect.Rect.TopLeft();
  395.  
  396.   // Give other views a chance to update
  397.   //
  398.   Invalidate(invView);    // refresh new image position
  399.   return HR_NOERROR;
  400. }
  401.  
  402. //
  403. // Set the part's site extent. This comes either after a SetPartRect, or for
  404. // open editing, comes alone.
  405. //
  406. HRESULT _IFUNC
  407. TOcPart::SetSiteExtent(const TSize far* newSize)
  408. {
  409.   PRECONDITION(newSize);
  410.   if (!newSize)
  411.     return HR_INVALIDARG;
  412.  
  413.   TOcView* view = OcDocument.GetActiveView();
  414.   if (!view)
  415.     return HR_FAIL;
  416.  
  417.   // Only accept server's size if we don't have a size yet. Always say OK.
  418.   //
  419. //  if (Size.cx > 0 && Size.cy > 0)
  420. //    return HR_NOERROR;
  421.  
  422.   // Give other views a chance to update
  423.   //
  424.   Invalidate(invView); // display new image
  425.  
  426.   TSize ext(*newSize);
  427.   TOcSiteRect siteRect(this, TRect(Pos, ext));
  428.  
  429.   if (view->ContainerHost->EvOcViewSetSiteRect(siteRect))
  430.     Size = siteRect.Rect.Size();
  431.   else
  432.     //\\// container doesn't accept server size (keep what we have)
  433.     return HR_FAIL;
  434.  
  435.   // Give other views a chance to update
  436.   //
  437.   Invalidate(invView);    // refresh new image position
  438.  
  439.   return HR_NOERROR;
  440. }
  441.  
  442. //
  443. // Get parent window for part
  444. //
  445. HRESULT _IFUNC
  446. TOcPart::GetParentWindow(HWND FAR *hWnd)
  447. {
  448.   TOcView* activeView = OcDocument.GetActiveView();
  449.   *hWnd = activeView->GetWindow();
  450.   return 0;
  451. }
  452.  
  453. //
  454. // Get zoom factor for part
  455. //
  456. HRESULT _IFUNC
  457. TOcPart::GetZoom(TOcScaleInfo* zoom)
  458. {
  459.   PRECONDITION(zoom);
  460.   if (!zoom)
  461.     return HR_INVALIDARG;
  462.  
  463.   TOcView* view = OcDocument.GetActiveView();
  464.   if (!view)
  465.     return HR_FAIL;
  466.  
  467.   TOcScaleFactor scaleFactor(*zoom);
  468.   if (!view->ContainerHost->EvOcViewGetScale(scaleFactor)) {
  469.     zoom->xD = zoom->xN = zoom->yD = zoom->yN = 1;
  470.   }
  471.   else
  472.     scaleFactor.GetScaleFactor(*zoom);
  473.  
  474.   return HR_NOERROR;
  475. }
  476.  
  477. //
  478. // Invalidate the site within the active view
  479. //
  480. void _IFUNC
  481. TOcPart::Invalidate(TOcInvalidate type)
  482. {
  483.   TOcView* view = OcDocument.GetActiveView();
  484.   TOcPartChangeInfo changeInfo(this, type);
  485.   if (view)
  486.     view->InvalidatePart(changeInfo);
  487. }
  488.  
  489. void _IFUNC
  490. TOcPart::OnSetFocus(BOOL set)
  491. {
  492.   TOcView* view = OcDocument.GetActiveView();
  493.   if (view && set)
  494.     ::SetFocus(view->GetWindow());
  495. }
  496.  
  497. HRESULT _IFUNC
  498. TOcPart::Init(IBDataProvider far*, IBPart far*, LPCOLESTR, BOOL)
  499. {
  500.   return HR_FAIL; // never called
  501. }
  502.  
  503. void _IFUNC
  504. TOcPart::Disconnect()
  505. {
  506.   // no need to do anything
  507. }
  508.  
  509. //----------------------------------------------------------------------------
  510.  
  511. //
  512. // Save this part to storage. May be any of:
  513. //   Save to our storage : sameAsLoad==1
  514. //   Copy to a storage   : sameAsLoad==0, remember==0
  515. //   SaveAs a new storage: sameAsLoad==0, remember==1
  516. //
  517. bool
  518. TOcPart::Save(bool sameAsLoad, bool remember)
  519. {
  520.   STATSTG  statstg;
  521.   if (!HRSucceeded(Storage->Stat(&statstg, STATFLAG_NONAME)))
  522.     return false;
  523.  
  524.   TOcStorage* oldStorage = 0;
  525.  
  526.   // If not sameAsLoad, then we are saving to a new storage. Switch to that,
  527.   // at least for this save.
  528.   //
  529.   if (!sameAsLoad) {
  530.     oldStorage = Storage;
  531.     Storage = new TOcStorage(*OcDocument.GetStorage(), GetName(), true, STGM_READWRITE);
  532.   }
  533.  
  534.   // Create/open a stream in our storage to save part information
  535.   //
  536.   TOcStream  stream(*Storage, ::PartStreamName, true, statstg.grfMode);
  537.  
  538.   // Write TOcPart data into stream, Name was written by our Doc
  539.   //
  540.   if (!HRSucceeded(stream.Write(&Pos, sizeof Pos)))
  541.     return false;
  542.  
  543.   if (!HRSucceeded(stream.Write(&Size, sizeof Size)))
  544.     return false;
  545.  
  546.   if (!HRSucceeded(stream.Write(&Flags, sizeof Flags)))
  547.     return false;
  548.  
  549.   // Now have actual server part write itself to this storage
  550.   //
  551.   bool result = Save(Storage->GetIStorage(), sameAsLoad, remember);
  552.  
  553.   // If this is a different storage, then either save it (remember) or put
  554.   // it back & clean up.
  555.   //
  556.   if (!sameAsLoad) {
  557.     if (remember) {
  558.       delete oldStorage;
  559.     }
  560.     else {
  561.       delete Storage;
  562.       Storage = oldStorage;
  563.     }
  564.   }
  565.  
  566.   return result;
  567. }
  568.  
  569. //
  570. // Load this part from its ocpart stream in its current storage
  571. //
  572. bool
  573. TOcPart::Load()
  574. {
  575.   // Open a stream with oc part information
  576.   //
  577.   STATSTG statstg;
  578.   if (!HRSucceeded(Storage->Stat(&statstg, STATFLAG_NONAME)))
  579.     return false;
  580.   TOcStream  stream(*Storage, ::PartStreamName, false, statstg.grfMode);
  581.  
  582.   // Read TOcPart data from stream. Server part info will be read in as needed
  583.   // after Init()
  584.   //
  585.   if (!HRSucceeded(stream.Read(&Pos, sizeof Pos)))
  586.     return false;
  587.  
  588.   if (!HRSucceeded(stream.Read(&Size, sizeof Size)))
  589.     return false;
  590.  
  591.   if (!HRSucceeded(stream.Read(&Flags, sizeof Flags)))
  592.     return false;
  593.   Flags &= ~(Closing | Active); // These Flags are not persistent
  594.  
  595.   return true;
  596. }
  597.  
  598. //
  599. // Update this part's idea of its size via the server, & then return that.
  600. // Use GetRect() to just get the current site rect.
  601. //
  602. TSize
  603. TOcPart::GetSize() const
  604. {
  605.   BPartI->GetPartSize(&const_cast<TSize&>(Size));
  606.   return Size;
  607. }
  608.  
  609. //
  610. // Set part to the new position given in logical units
  611. // NOTE: Does you update the part's location.
  612. //       Must explicitly call UpdateRect!
  613. //
  614. void
  615. TOcPart::SetPos(const TPoint& pos)
  616. {
  617.   Pos = pos;
  618. }
  619.  
  620. //
  621. // Set part to the new size given in logical units
  622. // NOTE: Does you update the part's location.
  623. //       Must explicitly call UpdateRect!
  624. //
  625. void
  626. TOcPart::SetSize(const TSize& size)
  627. {
  628.   Size = size;
  629. }
  630.  
  631. //
  632. // Set part to the new rect given in logical units
  633. //
  634. void
  635. TOcPart::UpdateRect()
  636. {
  637.   // Use device units for Bolero
  638.   //
  639.   TOcView* view = OcDocument.GetActiveView();
  640.   if (!view)
  641.     return;
  642.  
  643.   TOcSiteRect siteRect(this, TRect(Pos, Size));
  644.   view->ContainerHost->EvOcViewGetSiteRect(siteRect);
  645.   BPartI->SetPartPos(&siteRect.Rect);
  646. }
  647.  
  648. //----------------------------------------------------------------------------
  649. // IBPart pass-thrus not inlined
  650. //
  651. bool
  652. TOcPart::Activate(bool activate)
  653. {
  654.   TOcView* activeView = OcDocument.GetActiveView();
  655.   CHECK(activeView);
  656.  
  657.   if (activate && activeView->GetActivePart())
  658.     if (!activeView->ActivatePart(0))  // deactivate currently active part, if any
  659.       return false;
  660.  
  661.   // Makes sure that the part gets the active view as its host.
  662.   // This is important in multi-view situation.
  663.   //
  664.   SetHost(activeView);
  665.   if (!HRSucceeded(BPartI->Activate(activate)))
  666.     return false;
  667.  
  668.   if (activate) {
  669.     Flags |= Active;
  670.     activeView->SetActivePart(this);
  671.   }
  672.   else {
  673.     Flags &= ~Active;
  674.     activeView->SetActivePart(0);
  675.   }
  676.   return true;
  677. }
  678.  
  679. void
  680. TOcPart::FinishLoading()
  681. {
  682.   // Load embeded object on demand
  683.   //
  684.   if (!BPartI) {
  685.     TOcInitInfo initInfo(ihEmbed, iwStorage, OcDocument.GetActiveView());
  686.     InitObj(&initInfo);
  687.   }
  688. }
  689.  
  690.  
  691. //
  692. // Set data into the server object
  693. //
  694. bool
  695. TOcPart::SetFormatData(TOcFormatInfo far* fmt, HANDLE data, bool release)
  696. {
  697.   IBPart2* bPartI2;
  698.   if (HRSucceeded(BPart->QueryInterface(IID_IBPart2, &(LPVOID)bPartI2)))
  699.     ((IBPart*)bPartI2)->Release();
  700.   else
  701.     return false;
  702.  
  703.   return HRSucceeded(bPartI2->SetFormatData(fmt, data, release));
  704. }
  705.  
  706.  
  707. bool
  708. TOcPart::Save(IStorage* storage, bool sameAsLoad, bool remember)
  709. {
  710.   PRECONDITION(storage);
  711.   if (BPartI)
  712.     return HRSucceeded(BPartI->Save(storage, sameAsLoad, remember));
  713.   return false;
  714. }
  715.  
  716. bool
  717. TOcPart::Draw(HDC dc, const TRect& pos, const TRect& clip, TOcAspect aspect)
  718. {
  719.   PRECONDITION(dc);
  720.  
  721.   // Don't draw anything if we are closing down the part
  722.   //
  723.   if (Flags & Closing)
  724.     return true;
  725.  
  726.   const RECTL posl = { pos.left, pos.top, pos.right, pos.bottom };
  727.   const RECTL clipl = { clip.left, clip.top, clip.right, clip.bottom };
  728.  
  729.   // Load embeded object on demand
  730.   //
  731.   if (!BPartI) {
  732.     TOcInitInfo initInfo(ihEmbed, iwStorage, OcDocument.GetActiveView());
  733.     InitObj(&initInfo);
  734.     // Update the link
  735.     //
  736.     if (IsLink()) {
  737.       TOcView* view = OcDocument.GetActiveView();
  738.       if (view)
  739.         view->UpdateLinks();
  740.     }
  741.  
  742.   }
  743.  
  744.   return HRSucceeded(BPartI->Draw(dc, &posl, &clipl, aspect, drNone));
  745. }
  746.  
  747. bool
  748. TOcPart::EnumVerbs(const TOcVerb& verb)
  749. {
  750.   if (BPartI)
  751.     return HRIsOK(BPartI->EnumVerbs(const_cast<TOcVerb*>(&verb)));
  752.  
  753.   return false;
  754. }
  755.  
  756. bool
  757. TOcPart::DoVerb(UINT whichVerb)
  758. {
  759.   if (BPartI) {
  760.     if (HRSucceeded(BPartI->DoVerb(whichVerb))) {
  761.       TOcView* activeView = OcDocument.GetActiveView();
  762.       CHECK(activeView);
  763.       activeView->SetActivePart(this);  // we may be activated now...
  764.       return true;
  765.     }
  766.   }
  767.   return false;
  768. }
  769.  
  770. int
  771. TOcPart::Detach()
  772. {
  773.   return OcDocument.GetParts().Detach(this);
  774. }
  775.  
  776. void
  777. TOcPart::SetVisible(bool visible)
  778. {
  779.   if (visible)
  780.     Flags |= Visible;
  781.   else
  782.     Flags &= ~Visible;
  783.  
  784.   if (IsActive())
  785.     BPartI->Show(visible);
  786.   else
  787.     Invalidate(invView);    // refresh new image position
  788. }
  789.  
  790.  
  791. //
  792. // Set the storage for this part
  793. //
  794. void
  795. TOcPart::SetStorage(IStorage* storage, bool remember)
  796. {
  797.   if (Storage && (storage == Storage->GetIStorage()))
  798.     return;
  799.  
  800.   if (remember)
  801.     delete Storage;
  802.  
  803.   if (storage)
  804.     Storage = new TOcStorage(storage);
  805.   else
  806.     Storage = 0;
  807. }
  808.  
  809.  
  810. //----------------------------------------------------------------------------
  811. // CdPartCollection
  812. //
  813.  
  814. TOcPartCollection::TOcPartCollection()
  815. :
  816.   TCVectorImp<TOcPart*>(0, 10)
  817. {
  818. }
  819.  
  820. TOcPartCollection::~TOcPartCollection()
  821. {
  822.   Clear();
  823. }
  824.  
  825. //
  826. // Release parts in the collection
  827. //
  828. void
  829. TOcPartCollection::Clear()
  830. {
  831.   for (int i = Count() - 1; i >= 0; i--) {
  832.     TOcPart* part = (TOcPart*)(*this)[i];
  833.     part->Release();
  834.   }
  835. }
  836.  
  837. //
  838. // walk thru Part collection & return the last one that logical point hits,
  839. // (first one in Z order)
  840. //
  841. TOcPart*
  842. TOcPartCollection::Locate(TPoint& logicalPoint)
  843. {
  844.   TRect hitRect(logicalPoint, TSize(1,1));
  845.  
  846.   TOcPart* p = 0;
  847.   for (TOcPartCollectionIter i(*this); i; i++)
  848.     if (i.Current()->IsVisible(hitRect))
  849.       p = (TOcPart*)i.Current();
  850.   return p;
  851. }
  852.  
  853. //
  854. // Select/unselect all parts
  855. //
  856. bool
  857. TOcPartCollection::SelectAll(bool select)
  858. {
  859.   for (TOcPartCollectionIter i(*this); i; i++)
  860.     i.Current()->Select(select);
  861.   return true;
  862. }
  863.  
  864. int
  865. TOcPartCollection::Detach(TOcPart* const& part, int del)
  866. {
  867.   int ret = Base::Detach(Find(part));
  868.   if (ret && del)
  869.     const_cast<TOcPart*>(part)->Release();
  870.   return ret;
  871. }
  872.  
  873. //---------------------------------  OcVerb  -----------------------------------
  874. //
  875. TOcVerb::TOcVerb()
  876. :
  877.   TypeName(0),
  878.   VerbName(0),
  879.   VerbIndex(0),
  880.   CanDirty(false)
  881. {
  882. }
  883.